Skip to content

feat: Digest mail notifications - eXIP7.3.0.22 - integration into feature/mips - #1117

Merged
azayati merged 6 commits into
feature/mipsfrom
exip-7.3.0.22-mips
Sep 11, 2026
Merged

feat: Digest mail notifications - eXIP7.3.0.22 - integration into feature/mips#1117
azayati merged 6 commits into
feature/mipsfrom
exip-7.3.0.22-mips

Conversation

@azayati

@azayati azayati commented Sep 10, 2026

Copy link
Copy Markdown
Member

eXIP 7.3.0.22 — Digest mail notifications · integration into feature/mips

The agenda category (invitation, date poll) and its line plugin, the actor declared on event notifications (so the event creator is left out of his own digest), the removal of the timezone synchronization now owned by social, and the cleanup of the legacy makeDigest overrides.

The 4 commit(s) replayed from feature/experience

21 files changed, 386 insertions(+), 210 deletions(-)

How this branch was built

exip-7.3.0.22-mips starts from origin/feature/mips and replays only the commits tagged eXIP7.3.0.22 (git cherry-pick -x, the original reference is in every message). The FB version-bump commit (Task-87990) and the commits of the other eXIPs present on feature/experience are deliberately left out — no pom.xml is touched.

Merge order

makeDigest is still an abstract method of commons-api on feature/mips; the other 18 PRs remove their overrides, so they only compile once commons is merged: commons#786 first (wait for the Nexus snapshot), then social#6093, then the 17 addons in any order.

Classification

N1 for the whole eXIP (Liquibase schema and JPA entities, the commons notification dispatcher, new REST endpoints, mass email sending). Approver ≠ author: this PR must be approved by an Architect / Senior Developer who knows it is N1, not on the AI review alone.

Already validated on feature/experience

Every US of the board (project 8372) is "Tested & Validated" by the PO, the legacy engine cleanup (EXO-90072, 19 repositories) included. Full functional test plan: capture, daily and weekly contents, timezones, catch-up at startup, safety cleanup, and non-regression of the instant notifications.

Knowledge: TODO — eng-standards PR to open (/domain-doc commons + social) before leaving draft

🤖 Generated with Claude Code

@azayati
azayati marked this pull request as ready for review September 10, 2026 09:55
@azayati
azayati requested a review from boubaker September 10, 2026 09:55
@azayati

azayati commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

AI review — Round #1 — eXIP 7.3.0.22 Digest mail notifications (agenda category + timezone sync removal)

Reviewed as one delivery with the 18 sibling PRs, against Tech Spec note 50469 and board 8372, at head ec456b2b.

🟢 Nitnotification-configuration.xml:387: the category <description> says "events, replies, reminders and date polls" while the category covers EventAddedNotificationPlugin and DatePollNotificationPlugin only. Fix: "event invitations and date polls".

Verified conform: category agenda, order 50, the two spec plugin ids; AgendaNotificationPlugin now sets from to the modifier's username for organization identities only — needed by the capture's actor exclusion, and harmless for the channels (nothing in commons' dispatcher or lifecycles reads getFrom()); AgendaDigestLinePlugin reads eventId (made public) and MODIFIER_IDENTITY_ID, converts the start to the recipient's zone and locale, keeps all-day dates unconverted, returns no line on a vanished event; three text-only keys in AgendaNotification_en.properties; the timezone-sync copies are gone (TimeZoneRest, updateUserTimeZone API/impl/test, UIPortalAgendaHead.gtmpl, webui-configuration.xml and its import, the agendaBaseExtension module and webpack entry) and a git grep over every local repo finds no remaining caller of /agenda/rest/timezone or updateUserTimeZone — social's UserTimeZoneService + /social/rest/timezone replace them; 6 line-plugin tests (JUnit 5).

Classification: N1 by aggregation with the eXIP (an endpoint is removed, none added). Compiles only once commons#786 is on Nexus; needs social#6093 at runtime for the timezone sync. Knowledge: line still TODO.

🤖 Generated with Claude Code

azayati and others added 5 commits September 11, 2026 11:10
… - eXIP7.3.0.22 (#1070)

(cherry picked from commit 8aedd27)
(cherry picked from commit 24854c6)
…- eXIP7.3.0.22 (#1099)

(cherry picked from commit 318d55e)
(cherry picked from commit 0ca4b70)
…9486_EXO-89487 - eXIP7.3.0.22 (#1107)

(cherry picked from commit 868486c)
(cherry picked from commit e458bf0)
…rs - EXO-90072 - eXIP7.3.0.22 (#1112)

(cherry picked from commit a5fcc9b)
(cherry picked from commit ec456b2)
…ations - EXO-89484 - eXIP7.3.0.22

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 26da3b5)
@boubaker

Copy link
Copy Markdown
Member

AI review — Round #2 (independent review, Architects Lead's reviewer)

Independent pass at 8acdb93e, as part of the 19-PR delivery reviewed against Tech Spec note 50469 and board 8372 (delivery summary on commons#786). The round-1 nit (category description) is ✅ fixed at head.

🟡 Medium — DatePollNotificationPlugin never sets from: the poll creator receives "New date poll" about his own poll

DatePollNotificationPlugin.java:81-84 — untouched by this PR, hence reported here rather than inline.

    notification.key(getId());
    if (event.getId() > 0) {
      setNotificationRecipients(identityManager, notification, spaceService, eventAttendees, event, typeModification, modifierId);
    }                                                                     // no setFrom(...) — unlike AgendaNotificationPlugin.java:89-94 in this same PR

NotificationUtils.setNotificationRecipients (util/NotificationUtils.java:254-293) puts every attendee in to, creator included, and the capture leaves the actor out only through StringUtils.equals(recipient, notification.getFrom()) (commons DigestServiceImpl.java:149); with from == null nobody is excluded. Spec §3 asks agenda to "declare the actor of its event notifications (the from), which the capture needs to leave the event creator out of his own digest" — done for EventAddedNotificationPlugin, missed for DatePollNotificationPlugin, the second of the two plugins the agenda category covers.

Fix: the same block as AgendaNotificationPlugin.java:89-94 (resolve modifierId, setFrom(remoteId) when the identity is an organization one) in DatePollNotificationPlugin.makeNotification, plus one AgendaDigestLinePluginTest-style case asserting the creator is not in the captured recipients.

🟢 Nit — unused imports in AgendaUserSettingsServiceTest.java:30-32 (CommonsUtils, OrganizationService, UserProfile) left by the timezone-method removal. Knowledge: still TODO.

Verified conform: category agenda (order 50) covers exactly the two spec plugin ids; storeEventParameters writes eventId and MODIFIER_IDENTITY_ID (an identity id) and AgendaDigestLinePlugin parses them as long / getIdentity(id); the start is converted to the recipient's zone and locale, all-day dates stay unconverted, no line on a vanished event; AgendaNotificationPlugin sets from for organization identities and modifierId is the acting user's identity on every create/update path (AgendaEventServiceImpl.java:740,784,1056); bundle locale.notification.AgendaNotification equals the PluginConfig.bundlePath, wordings equal board US06/US07 (incl. the .allDay variant); the timezone-sync copies (TimeZoneRest, updateUserTimeZone API/impl/test, UIPortalAgendaHead.gtmpl, webui-configuration.xml, the agendaBaseExtension module and webpack entry) are gone and neither agenda, agenda-connectors nor caldav-integration (at their develop / feature/mips heads) still calls them — social's UserTimeZoneService + /social/rest/timezone replace them; 6 line-plugin tests (JUnit 5, @ExtendWith(MockitoExtension.class)).

Classification: N1 by aggregation with the eXIP (an endpoint is removed, none added). Compiles once commons#786 is on Nexus; needs social#6093 at runtime for the timezone sync. Approver ≠ author, never on the AI review alone; Knowledge: line required before merge.

🤖 Generated with Claude Code

…XO-89484 - eXIP7.3.0.22

Prior this change, AgendaUserSettingsServiceTest still imported CommonsUtils,
OrganizationService and UserProfile, which only the removed
testupdateUserTimeZone case used: the timezone synchronization moved to social
in this eXIP.

After this commit, the three imports are gone and the class imports only what
its remaining cases use.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@azayati

azayati commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Thanks for the pass. Answers to both points, at head 7ae4bf3f.

🟡 DatePollNotificationPlugin without from — out of scope, and the behaviour does not occur

DatePollNotificationPlugin.java is not part of this eXIP's diff. git diff origin/feature/mips HEAD -- agenda-services/src/main/java/org/exoplatform/agenda/notification/plugin/DatePollNotificationPlugin.java returns nothing: the file is byte-identical to the merge target, this PR does not touch it, so the point is outside the scope of this review.

It is also moot on the substance. The plugin never calls setFrom, but it calls excludeDatePollActor right after setNotificationRecipients:

    if (event.getId() > 0) {
      setNotificationRecipients(identityManager, notification, spaceService, eventAttendees, event, typeModification, modifierId);
      excludeDatePollActor(notification, event, modifierId);
    }

and that method removes the actor from the recipient list itself:

  private void excludeDatePollActor(NotificationInfo notification, Event event, Long modifierId) {
    long actorId = modifierId != null && modifierId > 0 ? modifierId : event.getCreatorId();
    ...
    List<String> recipients = notification.getSendToUserIds()
                                          .stream()
                                          .filter(username -> !StringUtils.equals(username, actorIdentity.getRemoteId()))
                                          .collect(Collectors.toCollection(ArrayList::new));
    notification.to(recipients);
  }

It comes from commit cdb2ba9a "fix: Remove notification to the creator when creating a date poll - EXO-89975 (#1115)", already on feature/mips. Since the capture iterates getSendToUserIds(), the creator is not in it and is therefore neither notified instantly nor captured for the digest. The event.getCreatorId() fallback covers the creation path, modifierId covers the update path.

So the spec rule holds here through the recipient exclusion rather than through from. EventAddedNotificationPlugin needed from because its recipients do contain the actor; the date poll's do not. Nothing changed on this point — happy to add setFrom anyway, in a separate PR against its own task, if you prefer both plugins to declare the actor the same way.

🟢 Unused imports — fixed

7ae4bf3f removes CommonsUtils, OrganizationService and UserProfile from AgendaUserSettingsServiceTest: only the testupdateUserTimeZone case used them, and it went away with the move of the timezone synchronization to social. Checked that none of the three appears anywhere else in the class.

The Knowledge: line is still to be filled on the 19 descriptions, with the eng-standards PR refreshing the domain docs.

@boubaker

Copy link
Copy Markdown
Member

AI review — Round #3 (follow-up, final for the code)

Independent review, Architects Lead's reviewer, at head 7ae4bf3f (diff 8acdb93e..7ae4bf3f: 3 import lines removed, nothing else).

Status of the previous rounds

Round Finding Status
1 🟢 Category description names notifications the category does not cover ✅ fixed at 8acdb93e
2 🟡 DatePollNotificationPlugin never sets from, the poll creator gets his own poll in his digest Withdrawn — reviewer's error. The file is byte-identical to feature/mips and, at 8acdb93e already, makeNotification calls excludeDatePollActor(notification, event, modifierId) right after setNotificationRecipients (DatePollNotificationPlugin.java:88,107-121, from cdb2ba9a EXO-89975). The actor (modifierId, else event.getCreatorId()) is removed from getSendToUserIds() itself, which is the list the digest capture iterates, so the spec rule holds through the recipients and the from field is not needed here. The finding was taken from a read of the file before the branch was rebased and not re-verified at the head it was posted against. No separate setFrom PR is needed.
2 🟢 Unused imports in AgendaUserSettingsServiceTest ✅ fixed in 7ae4bf3fCommonsUtils, OrganizationService, UserProfile gone, none used elsewhere in the class
2 🟢 Knowledge: line TODO ❌ still open — a delivery-level field of the 19 bodies, tracked on commons#786

New findings

None. The only hunk since the last round is the import removal.

Verified conform (unchanged from Round #2, re-checked at head): category agenda (order 50) covers exactly the two spec plugin ids; AgendaNotificationPlugin sets from for organization identities; AgendaDigestLinePlugin reads eventId / MODIFIER_IDENTITY_ID as written, converts the start to the recipient's zone and locale, keeps all-day dates unconverted, gives no line on a vanished event; wordings equal board US06/US07; the timezone-sync copies are gone with no remaining caller in agenda, agenda-connectors or caldav-integration.

All findings from the previous rounds are resolved or withdrawn on this PR; nothing outstanding from the AI review side on the code. The Knowledge: body line remains a delivery-level prerequisite before the feature/mips merge.

Classification: N1 by aggregation with the eXIP (an endpoint is removed, none added). Compiles once commons#786 is on Nexus; needs social#6093 at runtime for the timezone sync. Approver ≠ author, never on the AI review alone.

🤖 Generated with Claude Code

@azayati
azayati requested review from boubaker and removed request for boubaker September 11, 2026 13:51
@azayati
azayati enabled auto-merge (squash) September 11, 2026 16:10
@azayati
azayati merged commit 44ce8b3 into feature/mips Sep 11, 2026
6 of 8 checks passed
@azayati
azayati deleted the exip-7.3.0.22-mips branch September 11, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants